<template>
  <div>
    <!-- 搜索框 -->
    <div class="map-box">
      <div class="label" v-if="labelText">关键字搜索</div>
      <el-input
        v-model="mapAddress"
        placeholder="请输入内容"
        id="tipinput"
        @keyup.enter.native="searchKeyWord"
      >
      </el-input>
      <el-button type="primary" @click="searchKeyWord"  icon="el-icon-search" ></el-button>
    </div>

    <!-- 搜索结果选择窗 -->
    <div class="map_search_result" v-if="addressListBoolean">
      <ul v-if="poiList && poiList.length > 0">
        <li  @click="markerResult(item)" v-for="(item, index) in poiList" :key="index">{{ item.name }}</li>
      </ul>
      <p v-else>暂无数据</p>
    </div>

    <!-- 地图 -->
    <div class="map-container" id="container" :style="styleObj"></div>
  </div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader';

export default {
  name: 'MapContainer',
  mixins: [], //混入
  components: {}, //组件
  props: {
    labelText: {
      type: String,
      default: '',
    },
    address: {
      type: String,
      default: '',
    },
    lng: {
      type: Number,
      default: 119.30692,
    },
    lat: {
      type: Number,
      default: 26.078093,
    },
    styleObj: {
      type: Object,
      default: () => {
        return {
          width: '100%',
          height: '500px',
        }
      },
    },
    addressListBoolean: {
      type: Boolean,
      default: false,
    }
  }, //集成属性
  data() {
    return {
      map: null,
      marker: null,
      positionInfo: {
        lng: 119.30692,
        lat: 26.078093,
        address: '1111',
        province: '',
        city: '',
        district: '',
        street: '',
        streetNumber: '',
        zipcode: '',
        country: '',
        township: '',
      },
      mapAddress: "",
      autoCompleteComponent: null,
      placeSearchComponent: null,
      poiList: [],
    };
  },
  computed: {},
  methods: {
    initPosition() {
      if (this.lng && this.lat) {
        this.$set(this.positionInfo, 'lng', this.lng);
        this.$set(this.positionInfo, 'lat', this.lat);
      } else {
        this.positionInfo.lng = 119.30692
        this.positionInfo.lat = 26.078093
      }
      this.mapAddress = this.address;
      this.$set(this.positionInfo, 'address', this.address);
      this.initAMap();
    },
    // 根据输入内容查询
    searchKeyWord() {
      this.placeSearchComponent.search(this.mapAddress, (status, result) => {
        if (status === 'complete' && result.info === "OK") {
          this.poiList = result.poiList.pois
        } else {
          this.poiList = []
          this.$message({
            message: "没有查到结果",
            type: "warning",
          });
        }
      })
    },

    //选择搜索的内容
    markerResult(data) {
      // 返回给父组件
      // this.$emit("pickPoint", {
      //   address: data.name
      // })
      this.mapAddress = data.name
      var marker = new AMap.Marker({
        position: [Number(data.location.lng), Number(data.location.lat)],
      });
      this.map.clearMap()// 清除所有覆盖物（点标志）
      this.map.add(marker)// 添加点标志
      this.showInfoWindow(marker);
      setTimeout(() => {
        this.map.setCenter(data.location);
        this.map.setZoom(15);
      }, 50)
    },

    /** 初始化搜索 */
    mapSearchInit(AMap) {
      let autoOptions = {
        city: "福州",
        input: "tipInput",
      }
      let placeSearchOptions = { // 设置PlaceSearch属性
        city: "福州",     // 城市
        type: "",         // 数据类别
        pageSize: 10,     // 每页结果数,默认10
        pageIndex: 1,     // 请求页码，默认1
        extensions: "base"// 返回信息详略，默认为base（基本信息）
      };
      let autoCompleteComponent = new AMap.Autocomplete(autoOptions);
      this.autoCompleteComponent = autoCompleteComponent;
      // 注册placeSearch组件
      this.placeSearchComponent = new AMap.PlaceSearch(placeSearchOptions)
    },

    initAMap() {
      window._AMapSecurityConfig = {
        securityJsCode: 'd48e7f2bd17c16b4cb757cffbb694b90', //「你申请的安全密钥」
      };
      AMapLoader.load({
        key: '2b05e7179f91bbd5c2c8b9780493cf28', // 申请好的Web端开发者Key，首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
        plugins: [
          'AMap.ToolBar',
          'AMap.Scale', 
          'AMap.Geocoder', 
          'AMap.Geolocation', 
          'AMap.PlaceSearch', 
          'AMap.AutoComplete', 
          'AMap.ElasticMarker',
          'AMap.CitySearch'
        ], // 需要使用的的插件列表，如比例尺'AMap.Scale'，支持添加多个如：['...','...']
        resizeEnable: true,
      }).then((AMap) => {

        this.map = new AMap.Map('container', {
          // 设置地图容器id
          viewMode: '3D', // 是否为3D地图模式
          zoom: 11,       // 初始化地图级别
          center: [this.positionInfo.lng, this.positionInfo.lat], // 初始化地图中心点位置
          scrollWheel: true,              // 是否开启鼠标滚轮缩放
        });

        this.getCurrentLocation();        // 获取当前定位
        this.geocoder = new AMap.Geocoder()
        this.mapSearchInit(AMap)

        this.map.addControl(new AMap.Scale())     // 在图面添加比例尺控件，展示地图在当前层级和纬度下的比例尺
        this.map.addControl(new AMap.ToolBar())   // 在图面添加鹰眼控件，在地图右下角显示地图的缩略图

        this.marker = new AMap.Marker({
          map: this.map,
          position: [119.30692, 26.078093],
          offset: new AMap.Pixel(-13, -30),
          icon: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
        });

        this.handleClick(AMap)            // 地图选点
      }).catch((e) => {
        console.log(e);
      });
    },

    // 声明点击事件的回调函数
    handleClick() {
      this.map.on('click', (e) => {
        let lng = this.positionInfo.lng = e.lnglat.lng
        let lat = this.positionInfo.lat = e.lnglat.lat

        console.log("handleClick", lng, lat)
        let marker = new AMap.Marker({
          position: new AMap.LngLat(lng, lat)
        })
        this.map.clearMap() // 清除所有覆盖物（点标志）
        this.map.add(marker)// 添加点标志
        let lnglat = [lng, lat]
        let that = this

        that.geocoder.getAddress(lnglat, function (status, result) {
          if (status === 'complete' && result.regeocode) {
            that.mapAddress = result.regeocode.formattedAddress;
            that.showInfoWindow(marker, result.regeocode.formattedAddress);//自定义信息窗体
            let thisPosition = {
              address: result.regeocode.formattedAddress,
              lng: lng,
              lat: lat
            };
            that.$emit("pickPoint", thisPosition) //返回给父组件
          } else {
            that.$message.error('根据经纬度查询地址失败')
          }
        })
      })
    },

    //获取当前定位
    getCurrentLocation() {
      const that = this;
      that.geolocation = new AMap.Geolocation({
        timeout: 5000,            // 超过3秒后停止定位，默认：5s
        enableHighAccuracy: true, // 进行浏览器原生定位的时候是否尝试获取较高精度
        zoomToAccuracy: true,     // 定位成功后是否自动调整级别
      });

      // 获取用户的精确位置，有失败几率,需要一个兜底措施
      that.geolocation.getCurrentPosition(function (status, result) {
        // 备注：getCurrentPosition方法会调用超时或失败：
        // Get geolocation time out：浏览器定位超时，包括原生的超时，可以适当增加超时属性的设定值以减少这一现象。
        // 另外还有个别浏览器（如google Chrome浏览器等）本身的定位接口是黑洞，通过其请求定位完全没有回应，也会超时返回失败。
        // Get geolocation failed：定位失败，Chrome、火狐以及部分套壳浏览器接入的定位服务在国外，有较大限制，失败率高。
        if (status == 'complete') {
          that.onComplete(result)
        } else {
          that.onError(result) //失败后可使用getCityInfo获取非精准定位（具体到省市）
        }
      });
    },

    //解析定位结果
    onComplete(data) {
      let lnglat = data.position;
      this.positionInfo.lng = lnglat[0]
      this.positionInfo.lat = lnglat[1]
      let marker = new AMap.Marker({  //创建标记
        position: new AMap.LngLat(lnglat[0], lnglat[1])
      })
      this.map.clearMap()   // 清除所有覆盖物（点标志）
      this.map.add(marker)  // 添加点标志
      let that = this
      // 经纬度转换为中文地址详情
      that.geocoder.getAddress(lnglat, function (status, result) {
        if (status === 'complete' && result.regeocode) {
          this.mapAddress = result.regeocode.formattedAddress;
          this.positionInfo.address = result.regeocode.formattedAddress;
          this.showInfoWindow(marker, this.mapAddress);  // 自定义信息窗体
        } else {
          that.$message.error('根据经纬度查询地址失败')
        }
      })
    },

    //解析定位错误信息
    onError(data) {
      this.getLngLatLocation()
    },

    //在获取具体定位失败时调用的代码：（非精准定位！！！）
    getLngLatLocation() {
      const that = this;
      that.geolocation.getCityInfo((status, result) => {

        if (status === 'complete') {
          let data = result.position
          that.positionInfo.lng = data[0]
          that.positionInfo.lat = data[1]
          that.positionInfo.address = result.province + result.city;
          that.mapAddress = result.province + result.city;
          that.showLocation(data, that.mapAddress)
        } else {
          that.$message.error('获取地址失败')
        }
      })
    },

    //新增标记
    showLocation(data, address) {
      let marker = new AMap.Marker({
        position: new AMap.LngLat(data[0], data[1]) //参数为经纬度
      })
      this.map.clearMap()// 清除所有覆盖物（点标志）
      this.map.add(marker)// 添加点标志
      this.showInfoWindow(marker, address);//自定义信息窗体
    },
    
    //自定义信息窗体
    showInfoWindow(marker, address) {
      let infoWindow = new AMap.InfoWindow({
        isCustom: true, //是否自定义信息窗体
        content: `<div style="background-color: white;padding: 0 5px; border-radius: 5px;border: 1px solid #cccccc;"> 地址：${address}</div>`,
        closeWhenClickMap: true,
        zIndex: 999,
        offset: new AMap.Pixel(0, -40)
      });
      infoWindow.open(this.map, marker.getPosition());
    },
  },
  beforeCreate: function() {},
  created: function() {},
  beforeMount: function() {},
  mounted: function() {
    this.initPosition();
  },
  beforeUpdate: function() {},
  updated: function() {},
  beforeDestroy: function() {
    this.map?.destroy();
  },
  destroyed: function() {},
};
</script>
<style scoped lang="scss">
.map-box {
  display: flex;
  align-items: center;
  justify-content: center;
  .label {
    width: 240px;
    font-size: 14px;
    color: #333;
    margin-bottom: 10px;
  }
}
.map-container {
  position: relative;
  padding: 0px;
  margin: 10px 0;
}
</style>
